import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_base_library/flutter_base_library.dart';

/// 位置枚举
enum ToastGravityMF {
  /// 顶部
  top,

  /// 中间
  center,

  /// 底部
  bottom
}

/// toast 显示时长
class DurationMF {
  /// 短时长
  static const short = Duration(milliseconds: 1000);

  /// 长时长
  static const long = Duration(milliseconds: 3000);
}

/// 通用的Toast组件
class ToastMF {
  /// Toast 距离顶部默认间距
  static const int _defaultTopOffset = 50;

  /// Toast 距离底部默认间距
  static const int _defaultBottomOffset = 50;

  static ToastView? preToastView;

  /// 显示在中间. 如不设置duration则会自动根据内容长度来计算 (更友好, 最长5秒)
  static void showInCenter({
    required String text,
    required BuildContext context,
    Duration? duration,
  }) {
    show(
      text,
      context,
      duration: duration,
      gravity: ToastGravityMF.center,
    );
  }

  /// 显示Toast, 如不设置duration则会自动根据内容长度来计算 (更友好, 最长5秒)
  static void show(
    String text,
    BuildContext context, {
    Duration? duration,
    Color? background,
    TextStyle textStyle = const TextStyle(fontSize: 16, color: Colors.white),
    double? radius,
    Image? preIcon,
    double? verticalOffset,
    VoidCallback? onDismiss,
    ToastGravityMF? gravity,
  }) {
    final OverlayState overlayState = Overlay.of(context);

    preToastView?._dismiss();
    preToastView = null;

    final double finalVerticalOffset = getVerticalOffset(
      context: context,
      gravity: gravity,
      verticalOffset: verticalOffset,
    );

    /// 自动根据内容长度来计算时长, 更加人性化
    final int autoDuration = min(text.length * 0.06 + 0.8, 5.0).ceil();
    final Duration finalDuration = duration ?? Duration(seconds: autoDuration);
    final OverlayEntry overlayEntry = OverlayEntry(builder: (context) {
      return ToastWidget(
        widget: ToastChild(
          background: background,
          radius: radius,
          msg: text,
          leading: preIcon,
          textStyle: textStyle,
          gravity: gravity,
          verticalOffset: finalVerticalOffset,
        ),
      );
    });
    final ToastView toastView =
        ToastView(overlayState: overlayState, overlayEntry: overlayEntry);
    preToastView = toastView;
    toastView.show(
      duration: finalDuration,
      onDismiss: onDismiss,
    );
  }

  /// 获取默认设置的垂直间距
  static double getVerticalOffset({
    required BuildContext context,
    ToastGravityMF? gravity,
    double? verticalOffset,
  }) {
    final double offset = verticalOffset ?? 0;
    final double defaultOffset;
    switch (gravity) {
      case ToastGravityMF.top:
        final offset = verticalOffset ?? _defaultTopOffset;
        defaultOffset = MediaQuery.of(context).viewInsets.top + offset;
        break;
      case ToastGravityMF.bottom:
        final offset = verticalOffset ?? _defaultBottomOffset;
        defaultOffset = MediaQuery.of(context).viewInsets.bottom + offset;
        break;
      default:
        defaultOffset = verticalOffset ?? 0;
        break;
    }

    return defaultOffset + offset;
  }
}

class ToastView {
  OverlayState overlayState;
  OverlayEntry overlayEntry;
  bool _isVisible = false;

  ToastView({
    required this.overlayState,
    required this.overlayEntry,
  });

  void show({required Duration duration, VoidCallback? onDismiss}) async {
    _isVisible = true;
    overlayState.insert(overlayEntry);
    Future.delayed(duration, () {
      _dismiss();
      onDismiss?.call();
    });
  }

  void _dismiss() {
    if (!_isVisible) return;
    _isVisible = false;
    overlayEntry.remove();
  }
}

class ToastChild extends StatelessWidget {
  final String msg;
  final double verticalOffset;
  final Color? background;
  final double? radius;
  final Image? leading;
  final ToastGravityMF? gravity;
  final TextStyle? textStyle;

  const ToastChild({
    super.key,
    required this.msg,
    required this.verticalOffset,
    this.background,
    this.radius,
    this.leading,
    this.gravity,
    this.textStyle,
  });

  Alignment get alignment {
    switch (gravity) {
      case ToastGravityMF.top:
        return Alignment.topCenter;
      case ToastGravityMF.bottom:
        return Alignment.bottomCenter;
      default:
        return Alignment.center;
    }
  }

  EdgeInsets get padding {
    switch (gravity) {
      case ToastGravityMF.top:
        return EdgeInsets.only(top: verticalOffset);
      case ToastGravityMF.bottom:
        return EdgeInsets.only(bottom: verticalOffset);
      default:
        return EdgeInsets.only(top: verticalOffset);
    }
  }

  InlineSpan get leadingSpan {
    if (leading == null) {
      return const TextSpan(text: '');
    }
    return WidgetSpan(
      alignment: PlaceholderAlignment.middle,
      child: leading!.paddingOnly(right: 6),
    );
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: MediaQuery.of(context).size.width,
      child: Container(
        padding: padding,
        alignment: alignment,
        width: MediaQuery.of(context).size.width,
        child: Container(
          decoration: BoxDecoration(
            color: background ?? const Color(0xFF222222),
            borderRadius: BorderRadius.circular(radius ?? 8),
          ),
          margin: const EdgeInsets.symmetric(horizontal: 20),
          padding: const EdgeInsets.fromLTRB(18, 10, 18, 10),
          child: RichText(
              text: TextSpan(children: <InlineSpan>[
            leadingSpan,
            TextSpan(text: msg, style: textStyle)
          ])),
        ),
      ),
    );
  }
}

class ToastWidget extends StatelessWidget {
  final Widget widget;

  const ToastWidget({super.key, required this.widget});

  /// 使用IgnorePointer，方便手势透传过去
  @override
  Widget build(BuildContext context) {
    return IgnorePointer(
      child: Material(
        color: Colors.transparent,
        child: widget,
      ),
    );
  }
}
